package com.inifitness.message.processor.message;

import java.util.Map;

import com.inifitness.common.event.event.MessageEvent;
import com.inifitness.common.event.expression.MessageParserContext;
import com.inifitness.message.service.EventTemplate;
import com.inifitness.sms.service.AliCloudSmsService;
import com.inifitness.sms.service.AliCloudSmsService.Message;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.CompositeStringExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

/**
 *
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @since 2024-05-29 12:50
 */
@Component
@Log4j2
@RequiredArgsConstructor
public class SmsProcessor implements MessageProcessor {
  private final AliCloudSmsService aliCloudSmsService;
  private static final int DESIGN_PARAM_SIZE = 8;

  @Override
  public void process(MessageEvent event, EventTemplate template) {
    Message sms = new Message("18561863379","燧石健身");
    sms.addParameters(getParameters(template.getTemplate(),event.payload()));
    aliCloudSmsService.sendSms(sms,"SMS_468430126");
    log.info(()-> MessageFormatter.format("消息内容：{}", parseMessage(event, template.getTemplate())));
  }

  @Override
  public String parseMessage(MessageEvent event, String template) {
    return template;
  }

  private Map<String, String> getParameters(String template,Object payload){
    @SuppressWarnings("unused")
    JSONObject payloadJson = JSONUtil.parseObj(payload);
    StandardEvaluationContext context = new StandardEvaluationContext(payload);
    ///////直接使用的话会报EL1008E: Property or field 'xxx' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public or not valid?
    ///////这里通过StandardEvaluationContext#addPropertyAccessor增加一个属性访问器MapAccessor来解决
    context.addPropertyAccessor(new MapAccessor());

    ///////这里模板使用的是${xxx}，与一般的#{}不同，需要自己重新写下ParserContext
    ExpressionParser parser = new SpelExpressionParser();
    ParserContext parserContext = new MessageParserContext();
    ///////
    /*
     * 这里开始与其他消息表达式的处理不一样
     * parser.parseExpression(template, parserContext) 这里是生成了一个CompositeStringExpression表达式，用于将模板拆分为多个Expression
     * 然后对每个Expression进行取值处理
     * @see org.springframework.expression.common.CompositeStringExpression#getValue(Object rootObject, Class<T> desiredResultType)
     */
    CompositeStringExpression expression = (CompositeStringExpression) parser.parseExpression(template, parserContext);

    Map<String, String> result = CollectionUtils.newHashMap(DESIGN_PARAM_SIZE);
    for (Expression exp : expression.getExpressions()) {
      String value = exp.getValue(context, payload, String.class);
      /*
       * 这里取巧了，如果表达式的值与表达式不一致，说明进行了替换，认为是变量
       */
      if (!exp.getExpressionString().equals(value)) {
        result.put(exp.getExpressionString(), value);
      }
    }
    return result;
  }
}
